
local file = io.open(arg[1],"rb");
assert(file,"open file error:"..arg[1]);

local checksum = function(str)
    local off = 1;
    local ret = 0;
    while(true)do
        local s1 =  string.sub(str,off,off+1);
        off = off+2;
        local s2 = string.sub(str,off,off+1);

        s1 = tonumber("0x"..s1);
        s2 = tonumber("0x"..s2);
        if(not s2)then
            w_sum = s1;
            break;
        end

        ret = ret + s1;
    end
    return  (0x01 + ~ret),w_sum;
end;

local big_endian = {
    b = function(str,off)
        return tonumber("0x"..string.sub(str,off,off+1));
    end,
    h = function(str,off)
        local a,b = tonumber("0x"..string.sub(str,off,off+1)),tonumber("0x"..string.sub(str,off+2,off+3));
        return a*0x100 + b;
    end,
    w = function(str,off)
        local a,b,c,d = tonumber("0x"..string.sub(str,off,off+1)),tonumber("0x"..string.sub(str,off+2,off+3)),
        tonumber("0x"..string.sub(str,off+4,off+5)),tonumber("0x"..string.sub(str,off+6,off+7));
        return a*0x1000000 + b*0x10000 + c*0x100 + d;
    end,
}

local little_endian = {
    b = function(str,off)
        return tonumber("0x"..string.sub(off,off+1));
    end,
    h = function(str,off)
        local b,a = tonumber("0x"..string.sub(str,off,off+1)),tonumber("0x"..string.sub(str,off+2,off+3));
        return a*0x100 + b;
    end,
    w = function(str,off)
        local d,c,b,a = tonumber("0x"..string.sub(str,off,off+1)),tonumber("0x"..string.sub(str,off+2,off+3)),
        tonumber("0x"..string.sub(str,off+4,off+5)),tonumber("0x"..string.sub(str,off+6,off+7));
        return a*0x1000000 + b*0x10000 + c*0x100 + d;
    end,
}


local ULBA = 0;
local format = string.format;
local endian = little_endian;       --默认
--打开文件
local s = file:read("*a");

local outAddr = function(addr)
    --0x0400: 1KB
    --0x0800: 2KB
    --0x1000: 4KB
    --0x2000: 8KB
    --0x4000: 16KB
    if((addr%0x400)==0)then
        print(format('echo "program:%08X"',addr));
    end
end

local outW = function(addr,dat)
    outAddr(addr);
    print(format("mww 0x%08X 0x%08X",ULBA*0x10000 + addr,dat));
end

local outH = function(addr,dat)
    outAddr(addr);
    print(format("mwh 0x%08X 0x%04X",ULBA*0x10000 + addr,dat));
end

local outB = function(addr,dat)
    outAddr(addr);
    print(format("mwb 0x%08X 0x%02X",ULBA*0x10000 + addr,dat));
end

for w in string.gmatch(s,":(%w+)")do
    local len = tonumber("0x"..string.sub(w,1,2));      --reclen

    local addr = tonumber("0x"..string.sub(w,3,6));     --offset
    local type = tonumber("0x"..string.sub(w,7,8));     --rectype

    local sum,w_sum = checksum(w);
    if(not (sum&0xff==w_sum)) then
        print("err!");
        os.exit(-1);
    end



    if(type==0)then
        --print(format("addr:%04X",addr));
        local off = 9;
        while(len>=4)do
            --处理32位整数
            local value = endian.w(w,off);
            off = off + 4 * 2;
            len = len - 4;
            outW(addr,value);
            addr = addr + 4;
        end

        while(len>=2)do
            --处理32位整数
            local value = endian.h(w,off);
            off = off + 2 * 2;
            len = len - 2;
            outH(addr,value);
            addr = addr + 2;
        end

        while(len>=1)do
            --处理32位整数
            local value = endian.b(w,off);
            off = off + 1 * 2;
            len = len - 2;
            outB(addr,value);
            addr = addr + 1;
        end


    elseif(type==1)then
        --结束.并且退出
        break;
    elseif(type==2)then
        print("unknown type "..type);
        os.exit(-1);
    elseif(type==3)then
        print("unknown type "..type);
        os.exit(-1);
    elseif(type==5)then
        local a,b,c,d =
        tonumber("0x"..string.sub(w,9,10)),tonumber("0x"..string.sub(w,11,12)),
        tonumber("0x"..string.sub(w,13,14)),tonumber("0x"..string.sub(w,15,16));
        local addr = a*0x1000000 + b*0x10000 + c*0x100 + d;
        -- 最后一个PC地址.一般指向reset_handle
        print(format("# set PC %08X",addr))
    elseif(type==4)then
        --Extended Linear Address Record
        --以大端序读取
        -- local a,b = tonumber("0x"..string.sub(w,9,10)),tonumber("0x"..string.sub(w,11,12));

        -- ULBA =  a * 0x100;
        -- ULBA =  b;
        ULBA = big_endian.h(w,9);
        --print(ULBA);
        --os.exit(1);
    else
        print("unknown type "..type);
        os.exit(-1);
    end
    --print(string.format("%04X,%02X,-%d",addr,len,type));
    --print(w);
end
